<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$

/**
 +------------------------------------------------------------------------------
 * Think扩展函数库 需要手动加载后调用或者放入项目函数库
 +------------------------------------------------------------------------------
 * @category   Think
 * @package  Common
 * @author   liu21st <liu21st@gmail.com>
 * @version  $Id$
 +------------------------------------------------------------------------------
 */

// 获取客户端IP地址
function get_client_ip(){
	if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
	$ip = getenv("HTTP_CLIENT_IP");
	else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
	$ip = getenv("HTTP_X_FORWARDED_FOR");
	else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
	$ip = getenv("REMOTE_ADDR");
	else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
	$ip = $_SERVER['REMOTE_ADDR'];
	else
	$ip = "unknown";
	return($ip);
}

/**
 +----------------------------------------------------------
 * 字符串截取，支持中文和其他编码
 +----------------------------------------------------------
 * @static
 * @access public
 +----------------------------------------------------------
 * @param string $str 需要转换的字符串
 * @param string $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 +----------------------------------------------------------
 * @return string
 +----------------------------------------------------------
 */
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) {
	if(function_exists("mb_substr"))
	$slice = mb_substr($str, $start, $length, $charset);
	elseif(function_exists('iconv_substr')) {
		$slice = iconv_substr($str,$start,$length,$charset);
	}else{
		$re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
		$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
		$re['gbk']	  = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
		$re['big5']	  = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
		preg_match_all($re[$charset], $str, $match);
		$slice = join("",array_slice($match[0], $start, $length));
	}
	if($suffix && $str != $slice) return $slice."...";
	return $slice;
}
/**
 +----------------------------------------------------------
 * 字符串截取，支持中文和其他编码
 +----------------------------------------------------------
 * @static
 * @access public
 +----------------------------------------------------------
 * @param string $str 需要转换的字符串
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param string $suffix 截断显示字符
 +----------------------------------------------------------
 * @return string
 +----------------------------------------------------------
 */
function mStr($str, $length, $charset="utf-8", $suffix=true){
	return msubstr($str, 0, $length, $charset, $suffix);
}
/**
 +----------------------------------------------------------
 * 产生随机字串，可用来自动生成密码 默认长度6位 字母和数字混合
 +----------------------------------------------------------
 * @param string $len 长度
 * @param string $type 字串类型
 * 0 字母 1 数字 其它 混合
 * @param string $addChars 额外字符
 +----------------------------------------------------------
 * @return string
 +----------------------------------------------------------
 */
function rand_string($len=6,$type='',$addChars='') {
	$str ='';
	switch($type) {
		case 0:
			$chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.$addChars;
			break;
		case 1:
			$chars= str_repeat('0123456789',3);
			break;
		case 2:
			$chars='ABCDEFGHIJKLMNOPQRSTUVWXYZ'.$addChars;
			break;
		case 3:
			$chars='abcdefghijklmnopqrstuvwxyz'.$addChars;
			break;
		default :
			// 默认去掉了容易混淆的字符oOLl和数字01，要添加请使用addChars参数
			$chars='ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'.$addChars;
			break;
	}
	if($len>10 ) {//位数过长重复字符串一定次数
		$chars= $type==1? str_repeat($chars,$len) : str_repeat($chars,5);
	}
	$chars   =   str_shuffle($chars);
	$str     =   substr($chars,0,$len);
	return $str;
}

/**
 +----------------------------------------------------------
 * 获取登录验证码 默认为4位数
 +----------------------------------------------------------
 * @param string $fmode 文件名
 +----------------------------------------------------------
 * @return string
 +----------------------------------------------------------
 */
function build_verify ($length=4,$mode=1) {
	return rand_string($length,$mode);
}

/**
 +----------------------------------------------------------
 * 字节格式化 把字节数格式为 B K M G T 描述的大小
 +----------------------------------------------------------
 * @return string
 +----------------------------------------------------------
 */
function byte_format($size, $dec=2) {
	$a = array("B", "KB", "MB", "GB", "TB", "PB");
	$pos = 0;
	while ($size >= 1024) {
		$size /= 1024;
		$pos++;
	}
	return round($size,$dec)." ".$a[$pos];
}

/**
 +----------------------------------------------------------
 * 检查字符串是否是UTF8编码
 +----------------------------------------------------------
 * @param string $string 字符串
 +----------------------------------------------------------
 * @return Boolean
 +----------------------------------------------------------
 */
function is_utf8($string) {
	return preg_match('%^(?:
		 [\x09\x0A\x0D\x20-\x7E]            # ASCII
	   | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
	   |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
	   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
	   |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
	   |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
	   | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
	   |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
   )*$%xs', $string);
}
/**
 +----------------------------------------------------------
 * 代码加亮
 +----------------------------------------------------------
 * @param String  $str 要高亮显示的字符串 或者 文件名
 * @param Boolean $show 是否输出
 +----------------------------------------------------------
 * @return String
 +----------------------------------------------------------
 */
function highlight_code($str,$show=false) {
	if(file_exists($str)) {
		$str    =   file_get_contents($str);
	}
	$str  =  stripslashes(trim($str));
	// The highlight string function encodes and highlights
	// brackets so we need them to start raw
	$str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);

	// Replace any existing PHP tags to temporary markers so they don't accidentally
	// break the string out of PHP, and thus, thwart the highlighting.

	$str = str_replace(array('&lt;?php', '?&gt;',  '\\'), array('phptagopen', 'phptagclose', 'backslashtmp'), $str);

	// The highlight_string function requires that the text be surrounded
	// by PHP tags.  Since we don't know if A) the submitted text has PHP tags,
	// or B) whether the PHP tags enclose the entire string, we will add our
	// own PHP tags around the string along with some markers to make replacement easier later

	$str = '<?php //tempstart'."\n".$str.'//tempend ?>'; // <?

	// All the magic happens here, baby!
	$str = highlight_string($str, TRUE);

	// Prior to PHP 5, the highlight function used icky font tags
	// so we'll replace them with span tags.
	if (abs(phpversion()) < 5)
	{
		$str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
		$str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
	}

	// Remove our artificially added PHP
	$str = preg_replace("#\<code\>.+?//tempstart\<br />\</span\>#is", "<code>\n", $str);
	$str = preg_replace("#\<code\>.+?//tempstart\<br />#is", "<code>\n", $str);
	$str = preg_replace("#//tempend.+#is", "</span>\n</code>", $str);

	// Replace our markers back to PHP tags.
	$str = str_replace(array('phptagopen', 'phptagclose', 'backslashtmp'), array('&lt;?php', '?&gt;', '\\'), $str); //<?
	$line   =   explode("<br />", rtrim(ltrim($str,'<code>'),'</code>'));
	$result =   '<div class="code"><ol>';
	foreach($line as $key=>$val) {
		$result .=  '<li>'.$val.'</li>';
	}
	$result .=  '</ol></div>';
	$result = str_replace("\n", "", $result);
	if( $show!== false) {
		echo($result);
	}else {
		return $result;
	}
}
/**
 * 过滤得到安全的html
 * @param string $text 待过滤的字符串
 * @param string $type 默认为string,可选项:INT,FLOAT,BOOL,WORD,ALNUM,CMD,BASE64,ARRAY,PATH,USERNAME
 * @param bool $tagsMethod true为开启黑名单，白名单失效。false为开启白名单，黑名单失效.
 * @param bool $attrMethod 同上
 * @param array $tags 标签的过滤白名单
 * @param array $attr 属性名的过滤白名单
 * @param array $tagsBlack 标签的过滤黑名单
 * @param array $attrBlack 标签中属性的过滤黑名单
 */
 function h($text,$type='html',$tagsMethod=true,$attrMethod=true,$xssAuto = 1,$tags=array(),$attr=array(),$tagsBlack=array(),$attrBlack=array()){

	//无标签格式
	$text_tags	=	'';

	//只存在字体样式
	$font_tags	=	'<i><b><u><s><em><strong><font><big><small><sup><sub><bdo><h1><h2><h3><h4><h5><h6>';

	//标题摘要基本格式
	$base_tags	=	$font_tags.'<p><br><hr><a><img><map><area><pre><code><q><blockquote><acronym><cite><ins><del><center><strike>';

	//兼容Form格式
	$form_tags	=	$base_tags.'<form><input><textarea><button><select><optgroup><option><label><fieldset><legend>';

	//内容等允许HTML的格式
	$html_tags	=	$base_tags.'<ul><ol><li><dl><dd><dt><table><caption><td><th><tr><thead><tbody><tfoot><col><colgroup><div><span><object><embed>';

	//专题等全HTML格式
	$all_tags	=	$form_tags.$html_tags.'<!DOCTYPE><html><head><title><body><base><basefont><script><noscript><applet><object><param><style><frame><frameset><noframes><iframe>';

	//过滤标签
	$text	=	strip_tags($text, ${$type.'_tags'} );

	//过滤攻击代码
	if($type!='all'){
		//过滤危险的属性，如：过滤on事件lang js
		while(preg_match('/(<[^><]+) (lang|onclick|onload|unload|onmouseover|onmouseup|onmouseout|onmousedown|onkeydown|onkeypress|onkeyup|onblur|onchange|onfocus|action|background|codebase|dynsrc|lowsrc)[^><]+/i',$text,$mat)){
			$text	=	str_ireplace($mat[0],$mat[1],$text);
		}
		while(preg_match('/(<[^><]+)(window\.|javascript:|js:|about:|file:|document\.|vbs:|cookie)([^><]*)/i',$text,$mat)){
			$text	=	str_ireplace($mat[0],$mat[1].$mat[3],$text);
		}
	}
	return $text;
}
//function h($text,$type,$tagsMethod=true,$attrMethod=true,$xssAuto = 1,$tags=array(),$attr=array(),$tagsBlack=array(),$attrBlack=array()){
//	if(!class_exists('Security')){
//		vendor('libs.SamLib.filter.Security','','.class.php');
//	}
//	$inputConfig ['tagsMethod'] = 1;  //默认开启黑名单
//	$inputConfig ['attrMethod'] = 1;  //默认开启黑名单
//	$inputConfig ['xssAuto'] = 1 ;    //默认开启黑名单
//	$inputConfig ['tagsFilter'] = array();  //默认白名单为空
//	$inputConfig ['attrFilter'] = array();  //默认白名单为空
//	$inputConfig ['tagBlacklist'] = array ('applet', 'body', 'bgsound', 'base', 'basefont', 'frame', 'frameset', 'head',
//											'html', 'id', 'iframe', 'ilayer', 'layer', 'link', 'meta', 'name',  'script',
//											'style', 'title', 'xml','vbscript','javascript','input','form','textarea','select','option','button'); //默认的黑名单
//	$inputConfig ['attrBlacklist'] = array ('action', 'codebase', 'dynsrc', 'lowsrc','onclick','onload','onsubmit'); //默认的黑名单
//
//	$filter = Security::getInstance($type,$inputConfig);
//
//	$filter->setTagsMethod($tagsMethod);
//	$filter->setAttrMethod($attrMethod);
//	$filter->setXss($xssAuto);
//	//白名单.当$tagsMethod=false的时候无效
//	!empty($tags) && $filter->setTagsFilter($tags);
//	!empty($attr) && $filter->setAttrFilter($attr);
//	//黑名单.当$tagsMethod=true时候有效
//	!empty($tagsBlack) && $filter->setTagBlacklist($tagsBlack);
//	!empty($attrBlack) && $filter->setAttrBlacklist($attrBlack);
//	return $filter->inputFilter($text);
//}

//输出纯文本
function t($text,$parseBr=false){
	$text	=	h($text,'text');
	if(!$parseBr){
		$text	=	str_ireplace(array("\r","\n","\t","&nbsp;"),'',$text);
		$text	=	htmlspecialchars($text,ENT_QUOTES);
	}else{
		$text	=	htmlspecialchars($text,ENT_QUOTES);
		$text	=	nl2br($text);
	}
	$text	=	trim($text);
	return $text;
}

/**
 +----------------------------------------------------------
 * 输入字符串的过滤
 +----------------------------------------------------------
 * @param string $string 需要过滤的字符串
 * @param mixed  $type   过滤的参数类型 t:去除html标签 h:保留html标签 o:逗号分隔的可选值
 +----------------------------------------------------------
 * @return mixed
 +----------------------------------------------------------
 */
function it($string,$type='h',$data=false){
	if(!get_magic_quotes_gpc()){
		$string	=	addslashes($string);
	}
	switch($type) {
		case 'i': {
			$string	=	intval($string);
			break;
		}
		case 't': {
			$string	=	h($string,'text');
			$string	=	htmlspecialchars($string,ENT_QUOTES);
			break;
		}
		case 'h': {
			$string	=	h($string,'html');
			break;
		}
		case 'o': {
			if(!in_array($string,$data)){
				return false;
			}
			break;
		}
		case 'n': {
			if(!is_numeric($string)){
				return false;
			}
			break;
		}
	}

	return $string;
}

/**
 +----------------------------------------------------------
 * 输入字符串的过滤
 +----------------------------------------------------------
 * @param string $string 需要过滤的字符串
 * @param mixed  $type   过滤的参数类型 t:去除html标签 h:保留html标签 o:逗号分隔的可选值
 +----------------------------------------------------------
 * @return mixed
 +----------------------------------------------------------
 */
function ot($string,$type='h',$data=false){
	$string	=	stripslashes($string);
	switch($type) {
		case 't': {
			$string	=	strip_tags($string);
			$string	=	htmlspecialchars_decode($string,ENT_QUOTES);
			break;
		}
		case 'h': {
			$string	=	h($string,'html');
			return $string;
			break;
		}
		case 'o': {
			if(!in_array($string,$data)){
				return false;
			}
			break;
		}
	}

	return $string;
}

//解析jsescape
function unescape($str) {
	$str = rawurldecode($str);
	preg_match_all("/(?:%u.{4})|.+/",$str,$r);
	$ar = $r[0];
	foreach($ar as $k=>$v) {
		if(substr($v,0,2) == "%u" && strlen($v) == 6)
		$ar[$k] = iconv("UCS-2","UTF-8",pack("H4",substr($v,-4)));
	}
	return join("",$ar);
}

//解析UBB
function ubb($Text) {
	$Text=trim($Text);
	//$Text=htmlspecialchars($Text);
	$Text=preg_replace("/\\t/is","  ",$Text);
	$Text=preg_replace("/\[h1\](.+?)\[\/h1\]/is","<h1>\\1</h1>",$Text);
	$Text=preg_replace("/\[h2\](.+?)\[\/h2\]/is","<h2>\\1</h2>",$Text);
	$Text=preg_replace("/\[h3\](.+?)\[\/h3\]/is","<h3>\\1</h3>",$Text);
	$Text=preg_replace("/\[h4\](.+?)\[\/h4\]/is","<h4>\\1</h4>",$Text);
	$Text=preg_replace("/\[h5\](.+?)\[\/h5\]/is","<h5>\\1</h5>",$Text);
	$Text=preg_replace("/\[h6\](.+?)\[\/h6\]/is","<h6>\\1</h6>",$Text);
	$Text=preg_replace("/\[separator\]/is","",$Text);
	$Text=preg_replace("/\[center\](.+?)\[\/center\]/is","<center>\\1</center>",$Text);
	$Text=preg_replace("/\[url=http:\/\/([^\[]*)\](.+?)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\2</a>",$Text);
	$Text=preg_replace("/\[url=([^\[]*)\](.+?)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\2</a>",$Text);
	$Text=preg_replace("/\[url\]http:\/\/([^\[]*)\[\/url\]/is","<a href=\"http://\\1\" target=_blank>\\1</a>",$Text);
	$Text=preg_replace("/\[url\]([^\[]*)\[\/url\]/is","<a href=\"\\1\" target=_blank>\\1</a>",$Text);
	$Text=preg_replace("/\[img\](.+?)\[\/img\]/is","<img src=\\1>",$Text);
	$Text=preg_replace("/\[color=(.+?)\](.+?)\[\/color\]/is","<font color=\\1>\\2</font>",$Text);
	$Text=preg_replace("/\[size=(.+?)\](.+?)\[\/size\]/is","<font size=\\1>\\2</font>",$Text);
	$Text=preg_replace("/\[sup\](.+?)\[\/sup\]/is","<sup>\\1</sup>",$Text);
	$Text=preg_replace("/\[sub\](.+?)\[\/sub\]/is","<sub>\\1</sub>",$Text);
	$Text=preg_replace("/\[pre\](.+?)\[\/pre\]/is","<pre>\\1</pre>",$Text);
	$Text=preg_replace("/\[email\](.+?)\[\/email\]/is","<a href='mailto:\\1'>\\1</a>",$Text);
	$Text=preg_replace("/\[colorTxt\](.+?)\[\/colorTxt\]/eis","color_txt('\\1')",$Text);
	$Text=preg_replace("/\[emot\](.+?)\[\/emot\]/eis","emot('\\1')",$Text);
	$Text=preg_replace("/\[i\](.+?)\[\/i\]/is","<i>\\1</i>",$Text);
	$Text=preg_replace("/\[u\](.+?)\[\/u\]/is","<u>\\1</u>",$Text);
	$Text=preg_replace("/\[b\](.+?)\[\/b\]/is","<b>\\1</b>",$Text);
	$Text=preg_replace("/\[quote\](.+?)\[\/quote\]/is"," <div class='quote'><h5>引用:</h5><blockquote>\\1</blockquote></div>", $Text);
	$Text=preg_replace("/\[code\](.+?)\[\/code\]/eis","highlight_code('\\1')", $Text);
	$Text=preg_replace("/\[php\](.+?)\[\/php\]/eis","highlight_code('\\1')", $Text);
	$Text=preg_replace("/\[sig\](.+?)\[\/sig\]/is","<div class='sign'>\\1</div>", $Text);
	$Text=preg_replace("/\\n/is","<br/>",$Text);
	return $Text;
}

// 随机生成一组字符串
function build_count_rand ($number,$length=4,$mode=1) {
	if($mode==1 && $length<strlen($number) ) {
		//不足以生成一定数量的不重复数字
		return false;
	}
	$rand   =  array();
	for($i=0; $i<$number; $i++) {
		$rand[] =   rand_string($length,$mode);
	}
	$unqiue = array_unique($rand);
	if(count($unqiue)==count($rand)) {
		return $rand;
	}
	$count   = count($rand)-count($unqiue);
	for($i=0; $i<$count*3; $i++) {
		$rand[] =   rand_string($length,$mode);
	}
	$rand = array_slice(array_unique ($rand),0,$number);
	return $rand;
}

//移除跨站攻击脚本
function remove_xss($val) {
	// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
	// this prevents some character re-spacing such as <java\0script>
	// note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
	$val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);

	// straight replacements, the user should never need these since they're normal characters
	// this prevents like <IMG SRC=@avascript:alert('XSS')>
	$search = 'abcdefghijklmnopqrstuvwxyz';
	$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	$search .= '1234567890!@#$%^&*()';
	$search .= '~`";:?+/={}[]-_|\'\\';
	for ($i = 0; $i < strlen($search); $i++) {
		// ;? matches the ;, which is optional
		// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars

		// @ @ search for the hex values
		$val = preg_replace('/(&#[xX]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
		// @ @ 0{0,7} matches '0' zero to seven times
		$val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
	}

	// now the only remaining whitespace attacks are \t, \n, and \r
	$ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'style', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
	$ra2 = array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
	$ra = array_merge($ra1, $ra2);

	$found = true; // keep replacing as long as the previous round replaced something
	while ($found == true) {
		$val_before = $val;
		for ($i = 0; $i < sizeof($ra); $i++) {
			$pattern = '/';
			for ($j = 0; $j < strlen($ra[$i]); $j++) {
				if ($j > 0) {
					$pattern .= '(';
					$pattern .= '(&#[xX]0{0,8}([9ab]);)';
					$pattern .= '|';
					$pattern .= '|(&#0{0,8}([9|10|13]);)';
					$pattern .= ')*';
				}
				$pattern .= $ra[$i][$j];
			}
			$pattern .= '/i';
			$replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
			$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
			if ($val_before == $val) {
				// no replacements were made, so exit the loop
				$found = false;
			}
		}
	}
	return $val;
}

/**
 +----------------------------------------------------------
 * 把返回的数据集转换成Tree
 +----------------------------------------------------------
 * @access public
 +----------------------------------------------------------
 * @param array $list 要转换的数据集
 * @param string $pid parent标记字段
 * @param string $level level标记字段
 +----------------------------------------------------------
 * @return array
 +----------------------------------------------------------
 */
function list_to_tree($list, $pk='id',$pid = 'pid',$child = '_child',$root=0)
{
	// 创建Tree
	$tree = array();
	if(is_array($list)) {
		// 创建基于主键的数组引用
		$refer = array();
		foreach ($list as $key => $data) {
			$refer[$data[$pk]] =& $list[$key];
		}
		foreach ($list as $key => $data) {
			// 判断是否存在parent
			$parentId = $data[$pid];
			if ($root == $parentId) {
				$tree[] =& $list[$key];
			}else{
				if (isset($refer[$parentId])) {
					$parent =& $refer[$parentId];
					$parent[$child][] =& $list[$key];
				}
			}
		}
	}
	return $tree;
}

/**
 +----------------------------------------------------------
 * 对查询结果集进行排序
 +----------------------------------------------------------
 * @access public
 +----------------------------------------------------------
 * @param array $list 查询结果
 * @param string $field 排序的字段名
 * @param array $sortby 排序类型
 * asc正向排序 desc逆向排序 nat自然排序
 +----------------------------------------------------------
 * @return array
 +----------------------------------------------------------
 */
function list_sort_by($list,$field, $sortby='asc') {
	if(is_array($list)){
		$refer = $resultSet = array();
		foreach ($list as $i => $data)
		$refer[$i] = &$data[$field];
		switch ($sortby) {
			case 'asc': // 正向排序
				asort($refer);
				break;
			case 'desc':// 逆向排序
				arsort($refer);
				break;
			case 'nat': // 自然排序
				natcasesort($refer);
				break;
		}
		foreach ( $refer as $key=> $val)
		$resultSet[] = &$list[$key];
		return $resultSet;
	}
	return false;
}

/**
 +----------------------------------------------------------
 * 在数据列表中搜索
 +----------------------------------------------------------
 * @access public
 +----------------------------------------------------------
 * @param array $list 数据列表
 * @param mixed $condition 查询条件
 * 支持 array('name'=>$value) 或者 name=$value
 +----------------------------------------------------------
 * @return array
 +----------------------------------------------------------
 */
function list_search($list,$condition) {
	if(is_string($condition))
	parse_str($condition,$condition);
	// 返回的结果集合
	$resultSet = array();
	foreach ($list as $key=>$data){
		$find   =   false;
		foreach ($condition as $field=>$value){
			if(isset($data[$field])) {
				if(0 === strpos($value,'/')) {
					$find   =   preg_match($value,$data[$field]);
				}elseif($data[$field]==$value){
					$find = true;
				}
			}
		}
		if($find)
		$resultSet[]     =   &$list[$key];
	}
	return $resultSet;
}

// 发送Http状态信息
function send_http_status($status) {
	static $_status = array(
	// Informational 1xx
	100 => 'Continue',
	101 => 'Switching Protocols',
	// Success 2xx
	200 => 'OK',
	201 => 'Created',
	202 => 'Accepted',
	203 => 'Non-Authoritative Information',
	204 => 'No Content',
	205 => 'Reset Content',
	206 => 'Partial Content',
	// Redirection 3xx
	300 => 'Multiple Choices',
	301 => 'Moved Permanently',
	302 => 'Moved Temporarily ',  // 1.1
	303 => 'See Other',
	304 => 'Not Modified',
	305 => 'Use Proxy',
	// 306 is deprecated but reserved
	307 => 'Temporary Redirect',
	// Client Error 4xx
	400 => 'Bad Request',
	401 => 'Unauthorized',
	402 => 'Payment Required',
	403 => 'Forbidden',
	404 => 'Not Found',
	405 => 'Method Not Allowed',
	406 => 'Not Acceptable',
	407 => 'Proxy Authentication Required',
	408 => 'Request Timeout',
	409 => 'Conflict',
	410 => 'Gone',
	411 => 'Length Required',
	412 => 'Precondition Failed',
	413 => 'Request Entity Too Large',
	414 => 'Request-URI Too Long',
	415 => 'Unsupported Media Type',
	416 => 'Requested Range Not Satisfiable',
	417 => 'Expectation Failed',
	// Server Error 5xx
	500 => 'Internal Server Error',
	501 => 'Not Implemented',
	502 => 'Bad Gateway',
	503 => 'Service Unavailable',
	504 => 'Gateway Timeout',
	505 => 'HTTP Version Not Supported',
	509 => 'Bandwidth Limit Exceeded'
	);
	if(array_key_exists($code,$_status)) {
		header('HTTP/1.1 '.$code.' '.$_status[$code]);
	}
}

// 发送常用http header信息
function send_http_header($type='utf8'){
	//utf8,html,wml,xml,图片、文档类型 等常用header
	switch($type){
		case 'utf8':
			header("Content-type: text/html; charset=utf-8");
			break;
		case 'xml':
			header("Content-type: text/xml; charset=utf-8");
			break;
	}
}

// bmp图像处理兼容函数
function imagecreatefrombmp($fname) {

	$buf	=	@file_get_contents($fname);

	if(strlen($buf)<54) return false;

	$file_header=unpack("sbfType/LbfSize/sbfReserved1/sbfReserved2/LbfOffBits",substr($buf,0,14));

	if($file_header["bfType"]!=19778) return false;
	$info_header=unpack("LbiSize/lbiWidth/lbiHeight/sbiPlanes/sbiBitCountLbiCompression/LbiSizeImage/lbiXPelsPerMeter/lbiYPelsPerMeter/LbiClrUsed/LbiClrImportant",substr($buf,14,40));
	if($info_header["biBitCountLbiCompression"]==2) return false;
	$line_len=round($info_header["biWidth"]*$info_header["biBitCountLbiCompression"]/8);
	$x=$line_len%4;
	if($x>0) $line_len+=4-$x;

	$img=imagecreatetruecolor($info_header["biWidth"],$info_header["biHeight"]);
	switch($info_header["biBitCountLbiCompression"]){
		case 4:
			$colorset=unpack("L*",substr($buf,54,64));
			for($y=0;$y<$info_header["biHeight"];$y++){
				$colors=array();
				$y_pos=$y*$line_len+$file_header["bfOffBits"];
				for($x=0;$x<$info_header["biWidth"];$x++){
					if($x%2)
					$colors[]=$colorset[(ord($buf[$y_pos+($x+1)/2])&0xf)+1];
					else
					$colors[]=$colorset[((ord($buf[$y_pos+$x/2+1])>>4)&0xf)+1];
				}
				imagesetstyle($img,$colors);
				imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
			}
			break;
		case 8:
			$colorset=unpack("L*",substr($buf,54,1024));
			for($y=0;$y<$info_header["biHeight"];$y++){
				$colors=array();
				$y_pos=$y*$line_len+$file_header["bfOffBits"];
				for($x=0;$x<$info_header["biWidth"];$x++){
					$colors[]=$colorset[ord($buf[$y_pos+$x])+1];
				}
				imagesetstyle($img,$colors);
				imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
			}
			break;
		case 16:
			for($y=0;$y<$info_header["biHeight"];$y++){
				$colors=array();
				$y_pos=$y*$line_len+$file_header["bfOffBits"];
				for($x=0;$x<$info_header["biWidth"];$x++){
					$i=$x*2;
					$color=ord($buf[$y_pos+$i])|(ord($buf[$y_pos+$i+1])<<8);
					$colors[]=imagecolorallocate($img,(($color>>10)&0x1f)*0xff/0x1f,(($color>>5)&0x1f)*0xff/0x1f,($color&0x1f)*0xff/0x1f);
				}
				imagesetstyle($img,$colors);
				imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
			}
			break;
		case 24:
			for($y=0;$y<$info_header["biHeight"];$y++){
				$colors=array();
				$y_pos=$y*$line_len+$file_header["bfOffBits"];
				for($x=0;$x<$info_header["biWidth"];$x++){
					$i=$x*3;
					$colors[]=imagecolorallocate($img,ord($buf[$y_pos+$i+2]),ord($buf[$y_pos+$i+1]),ord($buf[$y_pos+$i]));
				}
				imagesetstyle($img,$colors);
				imageline($img,0,$info_header["biHeight"]-$y-1,$info_header["biWidth"],$info_header["biHeight"]-$y-1,IMG_COLOR_STYLED);
			}
			break;
		default:
			return false;
			break;
	}
	return $img;
}
// bmp图像处理兼容函数
function imagebmp(&$im, $filename = '', $bit = 8, $compression = 0) {
	if (!in_array($bit, array(1, 4, 8, 16, 24, 32)))
	{
		$bit = 8;

	}
	else if ($bit == 32) // todo:32 bit
	{
		$bit = 24;
	}

	$bits = pow(2, $bit);

	// 调整调色板
	imagetruecolortopalette($im, true, $bits);
	$width = imagesx($im);
	$height = imagesy($im);
	$colors_num = imagecolorstotal($im);

	if ($bit <= 8)
	{
		// 颜色索引
		$rgb_quad = '';
		for ($i = 0; $i < $colors_num; $i ++)
		{
			$colors = imagecolorsforindex($im, $i);
			$rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0";         }

			// 位图数据
			$bmp_data = '';

			// 非压缩
			if ($compression == 0 || $bit < 8)
			{
				if (!in_array($bit, array(1, 4, 8)))
				{
					$bit = 8;
				}

				$compression = 0;

				// 每行字节数必须为4的倍数，补齐。


				$extra = '';
				$padding = 4 - ceil($width / (8 / $bit)) % 4;
				if ($padding % 4 != 0)
				{
					$extra = str_repeat("\0", $padding);
				}

				for ($j = $height - 1; $j >= 0; $j --)
				{
					$i = 0;
					while ($i < $width)
					{
						$bin = 0;
						$limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0;

						for ($k = 8 - $bit; $k >= $limit; $k -= $bit)
						{
							$index = imagecolorat($im, $i, $j);
							$bin |= $index << $k;
							$i ++;
						}

						$bmp_data .= chr($bin);
					}

					$bmp_data .= $extra;
				}
			}
			// RLE8 压缩
			else if ($compression == 1 && $bit == 8)
			{
				for ($j = $height - 1; $j >= 0; $j --)
				{
					$last_index = "\0";
					$same_num   = 0;
					for ($i = 0; $i <= $width; $i ++)
					{
						$index = imagecolorat($im, $i, $j);
						if ($index !== $last_index || $same_num > 255)
						{
							if ($same_num != 0)
							{
								$bmp_data .= chr($same_num) . chr($last_index);
							}

							$last_index = $index;
							$same_num = 1;
						}
						else
						{
							$same_num ++;
						}
					}

					$bmp_data .= "\0\0";
				}

				$bmp_data .= "\0\1";
			}

			$size_quad = strlen($rgb_quad);
			$size_data = strlen($bmp_data);
	}
	else
	{
		// 每行字节数必须为4的倍数，补齐。
		$extra = '';
		$padding = 4 - ($width * ($bit / 8)) % 4;
		if ($padding % 4 != 0)
		{
			$extra = str_repeat("\0", $padding);
		}

		// 位图数据
		$bmp_data = '';

		for ($j = $height - 1; $j >= 0; $j --)
		{
			for ($i = 0; $i < $width; $i ++)
			{
				$index = imagecolorat($im, $i, $j);
				$colors = imagecolorsforindex($im, $index);

				if ($bit == 16)
				{
					$bin = 0 << $bit;

					$bin |= ($colors['red'] >> 3) << 10;
					$bin |= ($colors['green'] >> 3) << 5;
					$bin |= $colors['blue'] >> 3;

					$bmp_data .= pack("v", $bin);
				}
				else
				{
					$bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']);
				}

				// todo: 32bit;
			}

			$bmp_data .= $extra;
		}

		$size_quad = 0;
		$size_data = strlen($bmp_data);
		$colors_num = 0;
	}

	// 位图文件头
	$file_header = "BM" . pack("V3", 54 + $size_quad + $size_data, 0, 54 + $size_quad);

	// 位图信息头
	$info_header = pack("V3v2V*", 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0);
	// 写入文件
	if ($filename != '')
	{
		$fp = fopen("test.bmp", "wb");

		fwrite($fp, $file_header);
		fwrite($fp, $info_header);
		fwrite($fp, $rgb_quad);
		fwrite($fp, $bmp_data);
		fclose($fp);

		return 1;
	}

	// 浏览器输出
	header("Content-Type: image/bmp");
	echo $file_header . $info_header;
	echo $rgb_quad;
	echo $bmp_data;

	return 1;
}

//友好时间显示
function friendlyDate($sTime,$type = 'normal',$alt = 'false') {
	//sTime=源时间，cTime=当前时间，dTime=时间差
	$cTime		=	time();
	$dTime		=	$cTime - $sTime;
	$dDay		=	intval(date("Ymd",$cTime)) - intval(date("Ymd",$sTime));
	$dYear		=	intval(date("Y",$cTime)) - intval(date("Y",$sTime));
	//normal：n秒前，n分钟前，n小时前，日期
	if($type=='normal'){
		if( $dTime < 60 ){
			return $dTime."秒前";
		}elseif( $dTime < 3600 ){
			return intval($dTime/60)."分钟前";
		}elseif( $dTime >= 3600 && $dDay == 0  ){
			return intval($dTime/3600)."小时前";
		}elseif($dYear==0){
			return date("Y-m-d H:i",$sTime);
		}else{
			return date("Y-m-d H:i",$sTime);
		}
	}elseif($type=='mohu'){
		if( $dTime < 60 ){
			return $dTime."秒前";
		}elseif( $dTime < 3600 ){
			return intval($dTime/60)."分钟前";
		}elseif( $dTime >= 3600 && $dDay == 0  ){
			return intval($dTime/3600)."小时前";
		}elseif( $dDay > 0 && $dDay<3 ){
			return intval($dDay)."天前";
		}elseif( $dDay >= 3 ){
			return "3天前";
		}elseif( $dDay >= 30 ){
			return "1个月前";
		}
		//full: Y-m-d , H:i:s
	}elseif($type=='full'){
		return date("Y-m-d , H:i:s",$sTime);
	}elseif($type=='ymd'){
		return date("Y-m-d",$sTime);
	}else{
		if( $dTime < 60 ){
			return $dTime."秒前";
		}elseif( $dTime < 3600 ){
			return intval($dTime/60)."分钟前";
		}elseif( $dTime >= 3600 && $dDay == 0  ){
			return intval($dTime/3600)."小时前";
		}elseif($dYear==0){
			return date("Y-m-d H:i",$sTime);
		}else{
			return date("Y-m-d H:i",$sTime);
		}
	}
}

//获取用户姓名
function getUserName($uid,$lang=false){
	//判断语言
	$langSet	=	getLang();
	if($lang=='en' || $lang=='zh-cn'){
		$language	=	$lang;
	}elseif($langSet=='en' || $langSet=='zh-cn'){
		$language	=	$langSet;
	}else{
		$language	=	'zh-cn';
	}

	//开启了Memcached的处理过程
	if(C('MEMCACHED_ON') && class_exists('Memcached')){
		$mcache	=	new Memcached;
		$mcache->connect(C('MEMCACHED_HOST'),C('MEMCACHED_PORT'));
		$mkey	=	"username_{$language}_{$uid}";
		$username	=	$mcache->get($mkey);
		//缓存未命中，去数据库取
		if(!$username){
			if(is_numeric($uid)){
				$map['uid']   = $uid;
			}else{
				$map['uname'] = $uid;
			}
			$userinfo = M('User')->where($map)->field('uname,fullname,name')->find();
			//根据当前语言区分中英文名
			if($language=='en'){
//				//韦心红增加 2010-7-2
//				if($userinfo['uname']==$userinfo['name'] || empty($userinfo['name'])){
//					$sql = "SELECT baseInfo FROM `ts_space_info` where uid='$uid'";
//					$baseInfo = D('')->query( $sql );
//					$baseInfo = unserialize($baseInfo[0]['baseInfo']);
//					if($baseInfo['englishname']) $userinfo['name'] = $baseInfo['englishname'];
//				}

				$displayname	=	$userinfo['name'] ? $userinfo['name'] : $userinfo['uname'];
			}else{
				$displayname	=	$userinfo['fullname'] ? $userinfo['fullname'] : $userinfo['uname'];
			}

			$mcache->set($mkey,$displayname);
			return t($displayname);
		}else{
			return t($username);
		}
	}
	//未开启Memcached的过程
	else
	{
		static $_MapName = array();
		//缓存未命中，去数据库取
		if(!isset($_MapName[$language.'_'.$uid])){
			if(is_numeric($uid)){
				$map['uid']   = $uid;
			}else{
				$map['uname'] = $uid;
			}
			$userinfo = M('User')->where($map)->field('uname,fullname,name')->find();
			//根据当前语言区分中英文名
			if($language=='en'){
				//韦心红增加 2010-7-2
				if($userinfo['uname']==$userinfo['name'] || empty($userinfo['name'])){
					$sql = "SELECT baseInfo FROM `ts_space_info` where uid='$uid'";
					$baseInfo = D('')->query( $sql );
					$baseInfo = unserialize($baseInfo[0]['baseInfo']);
					if($baseInfo['englishname']) $userinfo['name'] = $baseInfo['englishname'];
				}

				$displayname	=	$userinfo['name'] ? $userinfo['name'] : $userinfo['uname'];
			}else{
				$displayname	=	$userinfo['fullname'] ? $userinfo['fullname'] : $userinfo['uname'];
			}
			$_MapName[$language.'_'.$uid] = $displayname;
			return t($displayname);
		}else{
			return t($_MapName[$language.'_'.$uid]);
		}
	}
}

//获取用户头像
function getUserFace($uid,$size='m'){
	$face	=	SITE_PATH.'/data/userface/'.$uid.'/middle_face.jpg';
	if( is_file($face) && filesize($face)>0 ){
		$filename = ($size=='m')?'middle_face.jpg':'small_face.jpg';
		return SITE_URL."/data/userface/$uid/$filename";
	}else{
		return THEME_URL."/images/user_pic.gif";
	}
}

//获取用户头衔
/*
 一级	0－100	 童
 二级	101－500	 秀
 三级	501－1000	 秀
 四级	1001－2500	 举
 五级	2501－5000	 举
 六级	5001－8000	 同进士出身
 七级	8001－12000	 同进士出身
 八级	12001－16000	 进士出身
 九级	16001－20000	 进士出身
 十级	20001－25000	 探
 十一级	25001－35000	 探花
 十二级	35001－50000	 榜眼
 十三级	50001－80000	 榜眼
 十四级	80001－120000	 状元
 十五级	120001－180000	 状元
 十六级	180001－250000	 大学
 十七级	250001－400000	 大学
 十八级	400001－	 翰林
 */
function getUserTitle($uid,$exp=false) {
	$title	=	array(
		'0-100'=>'童生',
		'101-500'=>'秀才',
		'501-1000'=>'秀才',
		'1001-2500'=>'举人',
		'2501-5000'=>'举人',
		'5001-8000'=>'同进士出身',
		'8001-12000'=>'同进士出身',
		'12001-16000'=>'进士出身',
		'16001-20000'=>'进士出身',
		'20001-25000'=>'探花',
		'25001-35000'=>'探花',
		'35001-50000'=>'榜眼',
		'50001-80000'=>'榜眼',
		'80001-120000'=>'状元',
		'120001-180000'=>'状元',
		'180001-250000'=>'大学士',
		'250001-400000'=>'大学士',
		'400001-99999999999'=>'翰林文圣',
	);
	//获取用户当前积分
	if($exp===false){
		$space	=	M()->table(C('DB_PREFIX').'space')->field('credit_exp')->where(" uid = '$uid' ")->find();
		$exp	=	$space['credit_exp'];
		if(!$exp) return false;
	}
	//获取用户头衔
	foreach($title as $k=>$v){
		$f	=	explode('-',$k);
		if($exp>=$f[0] && $exp<=$f[1]){
			return $v;
		}
	}
	return false;
}

/**
 * 去一个二维数组中的每个数组的固定的键知道的值来形成一个新的一维数组
 * @param $pArray 一个二维数组
 * @param $pKey 数组的键的名称
 * @return 返回新的一维数组
 */
function getSubByKey($pArray, $pKey="", $pCondition=""){
	$result = array();
	foreach($pArray as $temp_array){
		if(is_object($temp_array)){
			$temp_array = (array) $temp_array;
		}
		if((""!=$pCondition && $temp_array[$pCondition[0]]==$pCondition[1]) || ""==$pCondition) {
			$result[] = (""==$pKey) ? $temp_array : isset($temp_array[$pKey]) ? $temp_array[$pKey] : "";
		}
	}
	return $result;
}

function getMultiArraySubByKey($pArray,$pKey=""){
	$result = array();
	$result = getSubByKey($temp_array,$pKey);
	foreach($pArray as $temp_array){
		if(is_object($temp_array)){
			$temp_array = (array) $temp_array;
		}
		foreach ( $temp_array as $value){
			if(is_array($value)){
				$result = array_merge(getSubByKey($value,$pKey),$result);
			}
		}
	}
	return $result;
}

/**
 * 将两个二维数组根据指定的字段来连接起来，连接的方式类似sql查询中的连接
 * @param $pArray1 一个二维数组
 * @param $pArray2 一个二维数组
 * @param $pFields 作为连接依据的字段
 * @param $pType 连接的方式，默认为左联，即在右面的数组中没有找到匹配的则对应左面的行，否则不对应
 * @return 连接好的数组
 */
function arrayJoin($pArray1, $pArray2, $pFields, $pType="left"){
	$result = array();
	foreach($pArray1 as $row1)
	{
		$is_join = false;
		foreach($pArray2 as $row2)
		{
			if(canJoin($row1, $row2, $pFields))
			{
				$result[] = array_merge($row2, $row1);
				$is_join = true;
				break;
			}
		}

		//如果是左连接并且没有找到匹配的连接
		if($is_join==false && $pType=="left")
		{
			$result[] = $row1;
		}
	}
	return $result;
}

/**
 * 判断两个行是否满足连接条件
 * @author 常伟
 * @createTime 2004-07-15
 * @param $pRow1 数组的一行
 * @param $pRow2 数组的一行
 * @param $pFields 作为连接依据的字段
 * @return 是否可以连接
 */
function canJoin($pRow1, $pRow2, $pFields)
{
	$field_array = explode(",", $pFields);
	foreach($field_array as $key)
	{
		if(strtolower($pRow1[$key])!=strtolower($pRow2[$key]))
		return false;
	}
	return true;
}


/**
 * 根据指定的键对数组排序
 *
 * 用法：
 * @code php
 * $rows = array(
 *     array('id' => 1, 'value' => '1-1', 'parent' => 1),
 *     array('id' => 2, 'value' => '2-1', 'parent' => 1),
 *     array('id' => 3, 'value' => '3-1', 'parent' => 1),
 *     array('id' => 4, 'value' => '4-1', 'parent' => 2),
 *     array('id' => 5, 'value' => '5-1', 'parent' => 2),
 *     array('id' => 6, 'value' => '6-1', 'parent' => 3),
 * );
 *
 * $rows = Helper_Array::sortByCol($rows, 'id', SORT_DESC);
 * dump($rows);
 * // 输出结果为：
 * // array(
 * //   array('id' => 6, 'value' => '6-1', 'parent' => 3),
 * //   array('id' => 5, 'value' => '5-1', 'parent' => 2),
 * //   array('id' => 4, 'value' => '4-1', 'parent' => 2),
 * //   array('id' => 3, 'value' => '3-1', 'parent' => 1),
 * //   array('id' => 2, 'value' => '2-1', 'parent' => 1),
 * //   array('id' => 1, 'value' => '1-1', 'parent' => 1),
 * // )
 * @endcode
 *
 * @param array $array 要排序的数组
 * @param string $keyname 排序的键
 * @param int $dir 排序方向
 *
 * @return array 排序后的数组
 */
function sortByCol($array, $keyname, $dir = SORT_ASC)
{
	return sortByMultiCols($array, array($keyname => $dir));
}

/**
 * 将一个二维数组按照多个列进行排序，类似 SQL 语句中的 ORDER BY
 *
 * 用法：
 * @code php
 * $rows = Helper_Array::sortByMultiCols($rows, array(
 *     'parent' => SORT_ASC,
 *     'name' => SORT_DESC,
 * ));
 * @endcode
 *
 * @param array $rowset 要排序的数组
 * @param array $args 排序的键
 *
 * @return array 排序后的数组
 */
function sortByMultiCols($rowset, $args)
{
	$sortArray = array();
	$sortRule = '';
	foreach ($args as $sortField => $sortDir)
	{
		foreach ($rowset as $offset => $row)
		{
			$sortArray[$sortField][$offset] = $row[$sortField];
		}
		$sortRule .= '$sortArray[\'' . $sortField . '\'], ' . $sortDir . ', ';
	}
	if (empty($sortArray) || empty($sortRule)) { return $rowset; }
	eval('array_multisort(' . $sortRule . '$rowset);');
	return $rowset;
}


function getUserEmail($user,$replace = false){
	if($replace){
		$uname = $user;
	}else{
		$uname = model('User')->where('uid='.$user)->getField('email');
		return $uname;
	}

	return $uname."@notesmail.huawei.com";
}

function matchImages($content='') {
	$src	=	array();
	preg_match_all('/<img.*src=(.*)[>|\\s]/iU',$content,$src);
	if(count($src[1])>0){
		foreach($src[1] as $v){
			$images[] =	trim($v,"\"'");	//删除首尾的引号 ' "
		}
		return $images;
	}else{
		return false;
	}
}

function matchReplaceImages($content = ''){
	$image = preg_replace_callback('/<img.*src=(.*)[>|\\s]/iU',"matchReplaceImagesOnce",$content);
	return $image;
}

function matchReplaceImagesOnce($matches){
	$matches[1] = str_replace('"','',$matches[1]);
	return sprintf("<a class='thickbox'  href='%s'>%s</a>",$matches[1],$matches[0]);
}

function getSummary($content,$words,$max_desc_len=200){

	if(is_array($words)){
		$arrwords	=	$words;
	}else{
		$arrwords	=	explode(',',$words);
	}
	//$arrwords	=	array('挖掘'=>30,'频繁'=>20);

	//如果没有关键词,直接输出前几段
	if(count($arrwords)==0){
		$output	=	$content;

	//有关键词，输出带关键词的段落
	}else{
		//将内容拆分成数组
		$content	=	str_replace('\n','[]',$content);
		$content	=	str_replace('.','.[]',$content);
		$content	=	str_replace('。','。[]',$content);
		$docs		=	explode('[]',$content);
		$docs		=	array_filter($docs,'strlen');
		//记录每个关键词的在每段出现的次数和每段的权重，按权重排序
		$poss	=	0;
		$pos	=	true;
		foreach($docs as $key=>$content){
			foreach ( $arrwords as $word) {
				while ($pos) {
					$pos	=	mb_strpos ( $content, $word, $poss , 'utf8' );
					if($pos===false){
						break;
					}else{
						$pos_words['pos']			=	$pos;		//记录所有的关键词出现的位置
						$pos_words['word']			=	$word;		//记录每个位置的关键词
						$allpos[$key]['words'][]	=	$pos_words;	//记录段落关键词位置
						$allpos[$key]['weight']		+=	20;

						$poss	=	$pos+1;
						$pos	=	true;
					}
				}
				$poss	=	0;
				$pos	=	true;
			}
			$weight[$key]	=	intval($allpos[$key]['weight']);
		}
		$weight	=	array_flip($weight);
		krsort($weight);
		$weight	=	array_flip($weight);
		foreach($weight as $k=>$v){
			$summary[]	=	$docs[$k];
		}

		$output	=	array_slice($summary,0,2);
	}
	$output	=	getShort(implode('..',$output),$max_desc_len);
	//$output	=	implode('..',$output);
	return $output;
}

function getShort($str,$length=40) {
	$str	=	htmlspecialchars($str);
	$str	=	strip_tags($str);
	$str	=	htmlspecialchars_decode($str);
	$strlenth	=	0;
	$out		=	'';
	preg_match_all("/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/", $str, $match);
	foreach($match[0] as $v){
		preg_match("/[\xe0-\xef][\x80-\xbf]{2}/",$v, $matchs);
		if(!empty($matchs[0])){
			$strlenth	+=	1;
		}elseif(is_numeric($v)){
			$strlenth	+=	0.545;
		}else{
			$strlenth	+=	0.475;
		}

		if($strlenth>$length){
			break;
		}

		$output	.=	$v;
	}
	return $output;
}

//动态通知的评论两边的引号是否显示
function infoCss($info){
	if(empty($info)) return '';
	else             return "<div class='ico_cite C_C'>$info<span class='ico_cite2'></span></div>";
}


//加密函数
function jiami($txt,$key){
	if(empty($key)) $key = C('SECURE_CODE');
	$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=+";
	$nh = rand(0,64);
	$ch = $chars[$nh];
	$mdKey = md5($key.$ch);
	$mdKey = substr($mdKey,$nh%8, $nh%8+7);
	$txt = base64_encode($txt);
	$tmp = '';
	$i=0;$j=0;$k = 0;
	for ($i=0; $i<strlen($txt); $i++) {
		$k = $k == strlen($mdKey) ? 0 : $k;
		$j = ($nh+strpos($chars,$txt[$i])+ord($mdKey[$k++]))%64;
		$tmp .= $chars[$j];
	}
	return $ch.$tmp;
}
//解密函数
function jiemi($txt,$key){
	if(empty($key)) $key = C('SECURE_CODE');
	$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=+";
	$ch = $txt[0];
	$nh = strpos($chars,$ch);
	$mdKey = md5($key.$ch);
	$mdKey = substr($mdKey,$nh%8, $nh%8+7);
	$txt = substr($txt,1);
	$tmp = '';
	$i=0;$j=0; $k = 0;
	for ($i=0; $i<strlen($txt); $i++) {
		$k = $k == strlen($mdKey) ? 0 : $k;
		$j = strpos($chars,$txt[$i])-$nh - ord($mdKey[$k++]);
		while ($j<0) $j+=64;
		$tmp .= $chars[$j];
	}
	return base64_decode($tmp);
}


//获取用户最新通知数
function getUserNewNotify( $uid ){
	return M('notify')->where("touid=$uid AND isread=0")->count();
}
//获取文件后缀对应的图标
function getExtIcon($ext) {
	$iconPath		=	THEME_PATH.'/images/fileicon/';
	$iconUrl		=	__THEME__.'/images/fileicon/';
	$fileIcon		=	$ext.'.gif';
	$defaultIcon	=	'File.gif';
	if(file_exists($iconPath.$fileIcon)){
		return $iconUrl.$fileIcon;
	}else{
		return $iconUrl.$defaultIcon;
	}
}
/**
 * 判断一个字符串是否是整数
 * @param unknown_type $pString
 * @return string|string|string
 */
function isNumber($pString){
	$length = strlen($pString);
	//空字符串返回不是整数
	if($length==0)
	{
		return false;
	}
	for($i=0;$i<$length;$i++)
	{
		//根据ASCII判断是否字符串中的每个字符都是数字
		if($pString[$i]<"0" || $pString[$i]>"9")
		{
			return false;
		}
	}
	return true;
}

   /**
     * 以数组中的一个字段的值为唯一索引返回一个三维数组
     * @param $pArray 一个二维数组
     * @param $pFieldBy 作为索引的字段的KEY值
     * @param $pIncludeFileld 可以定义返回的数组的包含的原数组的字段
     * @return 返回新的三维数组
     */
    function group($pArray, $pFieldBy, $pIncludeFileld=""){
        if($pIncludeFileld!="")
            $fields = explode(",", $pIncludeFileld);
        $result_array = array();

        for($i=0; $i<count($pArray); $i++){
            $group_key = $pArray[$i][$pFieldBy];
            if( !isset( $result_array[$group_key] ) ){
                $result_array[$group_key] = array();
            }

            if($pIncludeFileld!=""){
                $temp = array();
                foreach($fields as $field){
                    $temp[$field] = $pArray[$i][$field];
                }
                $result_array[$group_key][] = $temp;
            }else{
                $result_array[$group_key][] = $pArray[$i];
            }
        }
        return $result_array;
    }

    function getLang(){
        //语言包
        $langSet = C('DEFAULT_LANG');
        if (C('LANG_AUTO_DETECT')){
        	if(isset($_GET[C('VAR_LANGUAGE')])){// 检测浏览器支持语言
        		$langSet = $_GET[C('VAR_LANGUAGE')];// url中设置了语言变量
        		cookie('think_language',$langSet,3600);
        	}elseif(cookie('think_language'))// 获取上次用户的选择
        	$langSet = cookie('think_language');
        	elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){// 自动侦测浏览器语言
        		preg_match('/^([a-z\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
        		$langSet = $matches[1];
        		cookie('think_language',$langSet,3600);
        	}

        }
		$langSet	=	strtolower($langSet);
		if($langSet!='zh-cn'){
			$langSet	=	'en';
		}
        return $langSet;
    }
?>